package com.mt.restaurant.service.sale.impl;

import com.mt.restaurant.dao.sale.SaleOrderDao;

import com.mt.common.core.exception.BusinessException;
import com.mt.common.core.web.base.PageDTO;
import com.mt.common.core.web.base.PageResultDTO;
import com.mt.common.core.web.base.BaseEntity;
import com.mt.common.core.web.BaseService;
import com.mt.restaurant.dto.sale.ChangeMenuRecordDto;
import com.mt.restaurant.entity.sale.MenuSaleRecord;
import com.mt.restaurant.service.sale.MenuSaleRecordService;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import com.mt.restaurant.entity.sale.SaleOrder;
import com.mt.restaurant.service.sale.SaleOrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.TimeUnit;

import static cn.hutool.core.date.DateTime.now;

@Service
@Transactional
public class SaleOrderServiceBean extends BaseService implements SaleOrderService {

    private static Logger logger = LogManager.getLogger();

	@Autowired
	private SaleOrderDao saleOrderDao;

	@Resource
	private RedisTemplate<String, List<SaleOrder>> redisTemplate;

	@Autowired
	StringRedisTemplate stringRedisTemplate;

	@Autowired
	private MenuSaleRecordService menuSaleRecordService;
	/**
	 * 根据分页参数查询销售订单集合
	 *
	 * @param pageDTO 分页条件
	 */
	@Override
	public PageResultDTO findSaleOrders(PageDTO pageDTO){
        pageDTO.setStartIndex((pageDTO.getCurrentPage()-1)*pageDTO.getPageSize());
		//TODO:请在此校验参数的合法性
		this.validateFindSaleOrders(pageDTO);
		List<SaleOrder> saleOrderDTOS = this.saleOrderDao.findSaleOrders(pageDTO);
		Long totalCount = this.saleOrderDao.findSaleOrderTotalCount(pageDTO);

		PageResultDTO pageResultDTO = new PageResultDTO();
		pageResultDTO.setTotalCount(totalCount);
		pageResultDTO.setDatas(saleOrderDTOS);

		return pageResultDTO;
	}

	/**
	 * 查询全部销售订单集合
	 *
	 */
	@Override
	public List<SaleOrder> findAllSaleOrders(){
		return this.saleOrderDao.findAllSaleOrders();
	}

	/**
	 * 查询所有销售订单集合(只提取ID 和 Name)
	 *
	 */
	@Override
	public List<SaleOrder> findAllSaleOrdersWithIdName(){
		//TODO:请在此校验参数的合法性
		this.validateFindAllSaleOrdersWithIdName();
		return this.saleOrderDao.findAllSaleOrdersWithIdName();
	}

	/**
	 * 根据名称查询销售订单集合(只提取ID 和 Name)
	 *
	 * @param saleOrderName 名称
	 */
	@Override
	public List<SaleOrder> findSaleOrdersWithIdNameByName(String saleOrderName){
		//TODO:请在此校验参数的合法性
		this.validateFindSaleOrdersWithIdNameByName(saleOrderName);
		//TODO:缓存取对应参数
		Set<String> keys = stringRedisTemplate.keys("searchData:SaleOrder_where_saleOrderName_" + saleOrderName);
		List<SaleOrder> saleOrders = new ArrayList<>();
		if (keys.isEmpty()) {
		saleOrders = this.saleOrderDao.findSaleOrdersWithIdNameByName(saleOrderName);
		redisTemplate.opsForValue().set("searchData:SaleOrder_where_saleOrderName_" + saleOrderName, saleOrders, 30, TimeUnit.DAYS);
		} else {
		saleOrders = redisTemplate.opsForValue().get("searchData:SaleOrder_where_saleOrderName_" + saleOrderName);
		}
		return saleOrders;
	}

	/**
	 * 根据ID查询指定的销售订单(只提取ID 和 Name)
	 *
	 * @param saleOrderId Id
	 */
	@Override
	public SaleOrder findSaleOrdersWithIdNameById(Long saleOrderId){
		//TODO:请在此校验参数的合法性
		this.validateFindSaleOrdersWithIdNameById(saleOrderId);
		return this.saleOrderDao.findSaleOrdersWithIdNameById(saleOrderId);
	}

	/**
	 * 根据ID查询指定的销售订单
	 *
	 * @param saleOrderId Id
	 */
	@Override
	public SaleOrder findSaleOrder(Long saleOrderId){
		//TODO:请在此校验参数的合法性
		this.validateFindSaleOrder(saleOrderId);
		return this.saleOrderDao.findSaleOrder(saleOrderId);
	}

	/**
	 * 根据ID查询指定的销售订单(包含外键)
	 *
	 * @param saleOrderId Id
	 */
	@Override
	public SaleOrder findSaleOrderWithForeignName(Long saleOrderId){
		//TODO:请在此校验参数的合法性
		this.validateFindSaleOrderWithForeignName(saleOrderId);
		SaleOrder saleOrder = this.saleOrderDao.findSaleOrderWithForeignName(saleOrderId);
		saleOrder.setMenuSaleRecords(this.menuSaleRecordService.findMenuSaleRecordByOrderId(saleOrderId));
		return saleOrder;
	}

	/**
	 * 新增销售订单
	 *
	 * @param saleOrder 实体对象
	 */
	@Override
	public SaleOrder saveSaleOrder(SaleOrder saleOrder){
		//TODO:请在此校验参数的合法性
		this.validateSaveSaleOrder(saleOrder);
		//TODO:填充公共参数
		this.setSavePulicColumns(saleOrder);
		saleOrder.setSaleDate(new Date());
		saleOrder.setStatus("未结算");
		Long rows = this.saleOrderDao.saveSaleOrder(saleOrder);
		for (MenuSaleRecord menuSaleRecord:saleOrder.getMenuSaleRecords()) {
			menuSaleRecord.setSaleOrderId(saleOrder.getEid());
			menuSaleRecordService.saveMenuSaleRecord(menuSaleRecord);
		}

		if(rows != 1)
		{
			String error = "新增保存销售订单出错，数据库应该返回1,但返回了 "+rows;
			throw new BusinessException(error);
		}
		return saleOrder;
	}

	/**
	 * 更新销售订单
	 *
	 * @param saleOrder 实体对象
	 */
	@Override
	public SaleOrder updateSaleOrder(SaleOrder saleOrder){
		//TODO:请在此校验参数的合法性
		this.validateUpdateSaleOrder(saleOrder);
		Long rows = this.saleOrderDao.updateSaleOrder(saleOrder);
		if(rows != 1)
		{
			String error = "修改保存销售订单出错，数据库应该返回1,但返回了 "+rows+",数据可能被删除";
			throw new BusinessException(error);
		}
		return saleOrder;
	}

	/**
	 * 根据ID删除销售订单
	 *
	 * @param saleOrderId ID
	 */
	@Override
	public void deleteSaleOrder(Long saleOrderId){
		//TODO:请在此校验参数的合法性
		this.validateDeleteSaleOrder(saleOrderId);

		Map<Class<? extends BaseEntity>,EntityUsage> entityUsageMap = this.checkForeignEntity(SaleOrder.class, saleOrderId);
		if(entityUsageMap != null && entityUsageMap.size() >0){
			StringBuilder errors = new StringBuilder();
			errors.append("计划删除的数据正在被以下数引用\n");
			for(EntityUsage entityUsage : entityUsageMap.values()){
				errors.append("\t").append(entityUsage.getEntityLabel()).append("\n");
				for(Map.Entry<Long,String> entry : entityUsage.getUsageIdNames().entrySet() ){
					errors.append("\t\t").append(entry.getKey()).append("\t").append(entry.getValue()).append("\n");
				}
			}
			errors.append("，不能删除，请检查处理后再删除");
			throw  new BusinessException(errors.toString());
		}

		Long rows = this.saleOrderDao.deleteSaleOrder(saleOrderId);
		if(rows != 1){
			String error = "删除销售订单出错，数据可能已经被删除";
			throw new BusinessException(error);
		}
	}

	@Override
	public void changeOrderMenu(ChangeMenuRecordDto changeMenuRecordDto) {
		for (MenuSaleRecord menuSaleRecord:changeMenuRecordDto.getInsertRecords()) {
			menuSaleRecord.setSaleOrderId(changeMenuRecordDto.getOrderId());
			this.menuSaleRecordService.saveMenuSaleRecord(menuSaleRecord);
		}
		for (MenuSaleRecord menuSaleRecord:changeMenuRecordDto.getRemoveRecords()) {
			this.menuSaleRecordService.deleteMenuSaleRecord(menuSaleRecord.getEid());
		}
		for (MenuSaleRecord menuSaleRecord:changeMenuRecordDto.getUpdateRecords()) {
			this.menuSaleRecordService.updateMenuSaleRecord(menuSaleRecord);
		}
	}

	//TODO:---------------验证-------------------

	private void validateFindSaleOrders(PageDTO pageDTO) {
	//TODO:请使用下面方法添加数据过滤条件
	//		pageDTO.addFilter("creatorId",this.getLoginUserId());
	//TODO:请完善数据校验规则和数据权限判断，如果有问题请抛出异常，参看下面validateUpdateSaleOrder()写法
	}

	private void validateFindSaleOrdersWithIdNameByName(String saleOrderName) {
	//TODO:请完善数据校验规则和数据权限判断，如果有问题请抛出异常，参看下面validateUpdateSaleOrder()写法
	}


	private void validateFindAllSaleOrdersWithIdName() {
	//TODO:请完善数据校验规则和数据权限判断，如果有问题请抛出异常，参看下面validateUpdateSaleOrder()写法
	}

	private void validateFindSaleOrdersWithIdNameById(Long saleOrderId) {
	//TODO:请完善数据校验规则和数据权限判断，如果有问题请抛出异常，参看下面validateUpdateSaleOrder()写法
	}

	private void validateFindSaleOrder(Long saleOrderId) {
	//TODO:请完善数据校验规则和数据权限判断，如果有问题请抛出异常，参看下面validateUpdateSaleOrder()写法
	}

	private void validateFindSaleOrderWithForeignName(Long saleOrderId) {
	//TODO:请完善数据校验规则和数据权限判断，如果有问题请抛出异常，参看下面validateUpdateSaleOrder()写法
	}

	private void validateSaveSaleOrder(SaleOrder saleOrder) {
	//不为空判断
	if (saleOrder.getEid() != null || saleOrder.getCreatorId() != null || saleOrder.getCreateDatetime() != null) {
	throw new BusinessException("非法请求");
	}
	//TODO:请完善数据校验规则和数据权限判断，如果有问题请抛出异常，参看下面validateUpdateSaleOrder()写法
	}

	private void validateUpdateSaleOrder(SaleOrder saleOrder) {
	//不为空判断
	if (saleOrder.getEid() == null) {
	throw new BusinessException("唯一标识不能为空");
	}
	//是否存在判断
	if (this.saleOrderDao.findSaleOrderTotalCount(PageDTO.create(SaleOrder.FIELD_ID, saleOrder.getEid())) == 0) {
	throw new BusinessException("修改的销售订单 " + saleOrder.getName() + " 不存在，修改失败，请重试或联系管理员");
	}
	//TODO:请完善数据校验规则和数据权限判断，如果有问题请抛出异常，参看下面validateUpdateSaleOrder()写法
	}

	private void validateDeleteSaleOrder(Long saleOrderId) {
	//TODO:请完善数据校验规则和数据权限判断，如果有问题请抛出异常，参看下面validateUpdateSaleOrder()写法
	}

	@Override
	public boolean canDownloadAttachment(String formName, Long id) {
	return true;
	}
}
